#include <stdio.h>
#include <set>
#include <unordered_map>

struct AppMsg {
    unsigned short msg_len;
    unsigned char msg_flag;     // 消息标志位
    unsigned char msg_cls;     // 消息类别
    unsigned short msg_id;
    unsigned char crc_code;     // crc 校验码
    unsigned long long context; // 保留上下文
};

typedef unsigned int handle;

class MsgEventHandler {
public:
    virtual ~MsgEventHandler() = default;
    virtual void onHandleEvent(AppMsg *msg, handle context) = 0;
};

class EventTrigger {
public:
    virtual ~EventTrigger() = default;
    virtual void listen(int msg_id, MsgEventHandler* pHandler) = 0;
    virtual void fireEvent(AppMsg* msg, handle context) = 0;
};

class MsgEventHandler2 {
public:
    virtual ~MsgEventHandler2() = default;
    virtual void onHandleEvent(AppMsg *msg, handle context) = 0;
};

class EventTrigger2 {
public:
    virtual ~EventTrigger2() = default;
    virtual void listen(int msg_id, MsgEventHandler* pHandler) = 0;
    virtual void fireEvent(AppMsg* msg, handle context) = 0;
};

class FunctionModule : public MsgEventHandler {
public:
    void regEvent(EventTrigger* trigger) {
        trigger->listen(1, this);
    }
    void onHandleEvent(AppMsg* msg, handle context) {
        switch (msg->msg_id) {
            case 1:
                //do something
                break;

            default:
                break;

        }
    }
};


typedef std::set<MsgEventHandler *> HandlerSet;
typedef std::unordered_map<int, HandlerSet> EventMap;

class EventDispatch : public EventTrigger {
public:
    virtual ~EventDispatch() = default;
    virtual void listen(int msg_id, MsgEventHandler* pHandler) {
        m_events[msg_id].insert(pHandler);
    }

    virtual void fireEvent(AppMsg* msg, handle context) {
        if (msg == nullptr) return;
        auto it = m_events.find(msg->msg_id);
        if (it == m_events.end()) return;

        for (const auto& pHandler : it->second) {
            if (pHandler == nullptr) continue;
            pHandler->onHandleEvent(msg, context);
        }
    }
protected:
    void handleEvent(const HandlerSet& sets, AppMsg *msg, handle context) {
        if (msg == nullptr) return;

        for (const auto& pHandler : sets) {
            if (pHandler == nullptr) continue;
            pHandler->onHandleEvent(msg, context);
        }
    }
private:
    EventMap m_events;
};
